/*
 * PuyoWindow.java
 *
 * Created on August 2, 2004 , PM 10:27
 */

/**package name of Puyo game*/
package Puyo;

//import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

/**
 * Puyo's Main Window, manage user interfaces such as keystroke events, image rendering
 * @author  Ming
 */
public class PuyoWindow extends GameCanvas implements Runnable{
    
  /**Main display*/
  Display mainDisplay;
  
  boolean showGameOver = false;
  
  boolean paused = false;
  
  /**contains game data and game logic*/
  PuyoLogic puyoLogic = null;

  /** 4 Puyo images, They are red, green, yellow, blue*/
  public Image puyoImages[];
  
  /*remove flickering*/
  private Image doubleBuffer;

  /*controlling the game speed. the smaller, the faster*/
  private int timeInterval = 200;
 
  /**speed change rate control*/
  double speedChangeRate = 1.25;

  private volatile Thread thread;

  /**Load puyo images, init GUIs*/
  public PuyoWindow(Display display) {
     super(true);     
     mainDisplay = display;
  }

  public void start() {
     puyoLogic = new PuyoLogic();  
     puyoImages = new Image[4];
     try{         
           puyoImages[0] = ScaleImage.scaleImage(
                   Image.createImage("/Puyo/images/puyo_red.png"),PuyoSettings.ballWidth,PuyoSettings.ballHeight);
           puyoImages[1] = ScaleImage.scaleImage(
                   Image.createImage("/Puyo/images/puyo_green.png"),PuyoSettings.ballWidth,PuyoSettings.ballHeight);
           puyoImages[2] = ScaleImage.scaleImage(
                   Image.createImage("/Puyo/images/puyo_blue.png"),PuyoSettings.ballWidth,PuyoSettings.ballHeight);
           puyoImages[3] = ScaleImage.scaleImage(
                   Image.createImage("/Puyo/images/puyo_yellow.png"),PuyoSettings.ballWidth,PuyoSettings.ballHeight);
     } catch (java.io.IOException exception) {
          exception.printStackTrace();
     }
     Thread runner = new Thread(this);
     runner.start();
  }
  
  /**tune up game speed*/
  public void speedUp(){
     timeInterval /= speedChangeRate;
  }
    
  /**tune down game speed*/
  public void speedDown(){
     timeInterval *= speedChangeRate;
  }
  
  public void keyPressed(int keyCode) {
    switch(keyCode){
        case KEY_STAR:
          speedUp();
          break;
        case KEY_POUND:
          speedDown();
          break;
    }
  }
  
  /**process user key input, primary way to interact with the game*/
  public void checkUserInput(){
  // get the state of keys
    int keyState = getKeyStates();
     if((keyState & UP_PRESSED) != 0) {         
          puyoLogic.rotateCW();
     }else if((keyState & DOWN_PRESSED) != 0){        
          puyoLogic.rotateCCW();
     }else if((keyState & LEFT_PRESSED) != 0){
          puyoLogic.moveLeft();
     }else if((keyState & RIGHT_PRESSED) != 0){         
          puyoLogic.moveRight();
     }      
  }

  /**draw puyo images according to the stored game data*/
  public void updateGameScreen(Graphics g){
     g.setColor(0xffffff);
     g.fillRect(0,0,PuyoSettings.canvasWidth,PuyoSettings.canvasHeight);    
        // draw the balls
     drawBalls(g);   
     if(showGameOver){
      g.setColor(0xff0000);
      g.drawString("GameOver",PuyoSettings.canvasWidth/2,PuyoSettings.canvasHeight/2, 
                    Graphics.TOP | Graphics.LEFT);    
     }
     
     if(puyoLogic != null){
      String s = "Score: " + puyoLogic.getScore();
      g.setColor(0xff00ff);
      g.drawString(s,PuyoSettings.canvasWidth-50,10, Graphics.TOP | Graphics.LEFT);      
     }
     flushGraphics();

  }
  
  private int color2ImageIndex(int color){
      return color-1;
  }
  
  private void drawBalls(Graphics g){
      if(puyoLogic != null ){
          //the boolean running is to prevent null pointer
        for(int i=0;i<puyoLogic.numDroppingBalls;i++){   
            if(puyoLogic.droppingBalls[i]!=null)
            g.drawImage(puyoImages[color2ImageIndex(puyoLogic.droppingBalls[i].color)],
                        (puyoLogic.droppingBalls[i].x-1)*PuyoSettings.ballWidth,                        
                        (PuyoSettings.boardHeight-puyoLogic.droppingBalls[i].y)*PuyoSettings.ballHeight,
                        Graphics.TOP | Graphics.LEFT);
        }
        for(int i=1;i<PuyoSettings.boardWidth+1;i++)
            for(int j=1;j<PuyoSettings.boardHeight+1;j++)
                if(puyoLogic.accumBalls[i][j] != puyoLogic.puyoEmpty){
                    g.drawImage(puyoImages[color2ImageIndex(puyoLogic.accumBalls[i][j])],
                        (i-1)*PuyoSettings.ballWidth,
                        (PuyoSettings.boardHeight-j)*PuyoSettings.ballHeight,
                        Graphics.TOP | Graphics.LEFT);
                }
      }
  }

// When the game canvas is hidden, stop the thread.

  protected void hideNotify(){
      thread = null;
  }

  /** When the canvas is shown, start a thread to
  *run the game loop.
  */
  protected void showNotify(){
   //     thread = new Thread( this );
   //     thread.start();
  }
  
  private void delay(int mseconds){
       try {
	   Thread.currentThread().sleep(mseconds);
       } catch(Exception e) {}
  }
  /**pause switch*/
  public void changePauseState(){
       paused = !paused;
  }  
  
  public void run() {
   
     while(true){      
       checkUserInput(); 
       updateGameScreen(getGraphics()); 
       delay(timeInterval);
       if(!paused && puyoLogic.drop()){ 
            updateGameScreen(getGraphics());             
            while(puyoLogic.checkAccumBalls()){ 
                 delay(2*timeInterval);                 
                 updateGameScreen(getGraphics()); 
                 while(puyoLogic.freeFalling());                                      
                  try {
		    Thread.currentThread().sleep(30);
		  } catch(Exception e) {}
                  updateGameScreen(getGraphics()); 
            }
                      
            if(!puyoLogic.initDroppingBalls()) {
                 showGameOver = true;
                 updateGameScreen(getGraphics());   
                 break;            
            }                  
        }       
        updateGameScreen(getGraphics());  
        delay(timeInterval);         
    }
  } 

} //class end
